
/**
 * \file etc.h
 * \author linyun <linyun@ysten.com>
 * \date 2011/12/14
 * 
 * This file includes etc_fns Configuration file operations.
 *
 */
#ifndef _INC_ETC_H_
#define _INC_ETC_H_

#ifdef __cplusplus
extern "C"
{
#endif							/* __cplusplus */

	/**
     * \defgroup etc_fns Configuration file operations
     *
     * The configuration file used by CMA have a similiar format as 
     * M$ Windows INI file, i.e. the file consists of sections, and 
     * the section consists of key-value pairs, like this:
     *
     * \code
     * [cma]
     * # ID
     * id=1234567890
     *
     * # ip
     * ip=192.168.1.10
     *
     * 
     * [wbcd]
     * ip=192.168.1.10
     * 
     * [cmd]
     * com=/dev/ttyS1
     * baudrate=9600
     * \endcode
     *
     * Assume that the configuration file named \a my.cfg, if you want get 
     * the value of \a mdev in \a system section, you can call 
     * \a GetValueFromEtcFile in the following way:
     *
     * \code
     * char buffer [51];
     *
     * GetValueFromEtcFile ("my.cfg", "system", "mdev", buffer, 51);
     * \endcode
     *
     * Example:
     *
     * \include cfgfile.c
     *
     * @{
     */


/**
 * \var typedef unsigned int GHANDLE
 * \brief etc handle.
 */
#ifndef GHANDLE
	typedef void *GHANDLE;
#endif

/**
 * \var typedef int BOOL
 * \brief A type definition for boolean value.
 */
#ifndef BOOL
#define BOOL		int
#endif

/**
 * \def FALSE
 * \brief FALSE value, defined as 0 by MiniGUI.
 */
#ifndef FALSE
#define FALSE	0
#endif

/**
 * \def TRUE
 * \brief TRUE value, defined as 1 by MiniGUI.
 */
#ifndef TRUE
#define TRUE		1
#endif

/**
 * \def NULL
 * \brief A value indicates null pointer.
 */
#ifndef NULL
#define NULL		((void *)0)
#endif

/**
* \def ETC_MAXLINE
* \brief The max line number of etc file.
**/
#define ETC_MAXLINE             1024

/**
* \def ETC_FILENOTFOUND
* \brief No found etc file.
**/
#define ETC_FILENOTFOUND        -1

/**
* \def ETC_SECTIONNOTFOUND
* \brief No found section in etc file.
**/
#define ETC_SECTIONNOTFOUND     -2

/**
* \def ETC_KEYNOTFOUND
* \brief No found key in etc file.
**/
#define ETC_KEYNOTFOUND         -3

/**
* \def ETC_TMPFILEFAILED
* \brief Create tmpfile failed.
**/
#define ETC_TMPFILEFAILED       -4

/**
* \def ETC_FILEIOFAILED
* \brief IO operation failed to etc file.
**/
#define ETC_FILEIOFAILED        -5

/**
* \def ETC_INTCONV
* \brief  Convert the value string to an integer failed.
**/
#define ETC_INTCONV             -6

/**
* \def ETC_INVALIDOBJ
* \brief Invalid object to etc file.
**/
#define ETC_INVALIDOBJ          -7

/**
* \def ETC_READONLYOBJ
* \brief Read only to etc file.
**/
#define ETC_READONLYOBJ         -8

/**
* \def ETC_OK
* \brief Operate success to etc file.
**/
#define ETC_OK                  0

/** Etc The current config section information */
	typedef struct _ETCSECTION
	{

	/** Allocated number of keys */
		int key_nr_alloc;

	/** Key number in the section */
		int key_nr;

	/** Name of the section */
		char *name;

	/** Array of keys */
		char **keys;

	/** Array of values */
		char **values;
	} ETCSECTION;

/** Data type of pointer to a ETCSECTION */
	typedef ETCSECTION *PETCSECTION;

/** ETC_S The current config file information*/
	typedef struct _ETC_S
	{

	/** Allocated number of sections */
		int sect_nr_alloc;

	/** Number of sections */
		int section_nr;

	/** Pointer to section arrays */
		PETCSECTION sections;
	} ETC_S;


/**
 * \fn int  GetValueFromEtcFile (const char* pEtcFile,\
                const char* pSection, const char* pKey, char* pValue, int iLen)
 * \brief Gets value from a configuration file.
 *
 * This function gets the value of the key \a pKey in the section \a pSection 
 * of the configuration file \a pEtcFile, and saves the value to the buffer
 * pointed to by \a pValue. 
 *
 * \param pEtcFile The path name of the configuration file.
 * \param pSection The section name in which the value located.
 * \param pKey The key name of the value.
 * \param pValue The value will be saved in this buffer.
 * \param iLen The length in bytes of the buffer.
 *
 * \return ETC_OK on success, < 0 on error.
 *
 * \retval ETC_OK               Gets value successfullly.
 * \retval ETC_FILENOTFOUND     Can not find the specified configuration file.
 * \retval ETC_SECTIONNOTFOUND  Can not find the specified section in the 
 *                              configuration file.
 * \retval ETC_KEYNOTFOUND      Can not find the specified key in the section.
 * \retval ETC_FILEIOFAILED     File I/O operation error occurred.
 *
 * \note MiniGUI use \a strncpy to copy actual value to \a pValue. Thus, 
 *       if the length of the actual value is larger than \a iLen, the 
 *       result copied to \a pValue will \em NOT be null-terminated.
 *
 * \sa GetIntValueFromEtcFile, SetValueToEtcFile, strncpy(3)
 */
	int GetValueFromEtcFile (const char *pEtcFile, const char *pSection, const char *pKey, char *pValue, int iLen);

/**
 * \fn int  GetIntValueFromEtcFile (const char* pEtcFile,\
                const char* pSection, const char* pKey, int* value)
 * \brief Gets integer value from a configuration file.
 *
 * This function gets the integer value of the key \a pKey in the section 
 * \a pSection of the configuration file \a pEtcFile, and returns the 
 * integer value through the buffer pointed to by \a value. 
 *
 * \param pEtcFile The path name of the configuration file.
 * \param pSection The section name in which the value located.
 * \param pKey The key name of the value.
 * \param value The integer value will be saved in this buffer.
 *
 * \return ETC_OK on success, < 0 on error.
 *
 * \retval ETC_OK               Gets value successfullly.
 * \retval ETC_FILENOTFOUND     Can not find the specified configuration file.
 * \retval ETC_SECTIONNOTFOUND  Can not find the specified section in the 
 *                              configuration file.
 * \retval ETC_KEYNOTFOUND      Can not find the specified key in the section.
 * \retval ETC_FILEIOFAILED     File I/O operation error occurred.
 * \retval ETC_INTCONV          Can not convert the value string to an integer.
 *
 * \note MiniGUI uses \a strtol to convert the string value to an integer, 
 *       and pass the base as 0. Thus, the valid string value can be 
 *       converted to integer should be in the following forms:
 *
 *  - [+|-]0x[0-9|A-F]*\n
 *    Will be read in base 16.
 *  - [+|-]0[0-7]*\n
 *    Will be read in base 8.
 *  - [+|-][1-9][0-9]*\n
 *    Will be read in base 10.
 *
 * \sa GetValueFromEtcFile, SetValueToEtcFile, strtol(3)
 */
	int GetIntValueFromEtcFile (const char *pEtcFile, const char *pSection, const char *pKey, int *value);

/**
 * \fn GHANDLE  LoadEtcFile (const char * pEtcFile)
 * \brief Loads an etc file into memory.
 *
 * This function loads the content of an etc file into the memory, later, you
 * can visit the content using \a GetValueFromEtc function.
 *
 * \param pEtcFile The path name of the configuration file.
 *        If pEtcFile is NULL, the function will create an empty ETC object.
 *
 * \return Handle of the etc object on success, NULL on error.
 *
 * \sa UnloadEtcFile, GetValueFromEtc
 */
	GHANDLE LoadEtcFile (const char *pEtcFile);

/**
 * \fn int  SaveEtcToFile (GHANDLE hEtc, const char* file_name);
 * \brief Saves an ETC object into a file.
 *
 * This function saves the etc object into the file named \a file_name;
 *
 * \param hEtc Handle to the etc object.
 * \param file_name The name of the target file.
 *
 * \return ETC_OK on success, 0 < on error.
 *
 * \retval ETC_OK               Sets the etc object successfullly.
 * \retval ETC_INVALIDOBJ       Invalid etc object.
 * \retval ETC_FILEIOFAILED     File I/O operation error occurred.
 *
 * \sa LoadEtcFile
 */
	int SaveEtcToFile (GHANDLE hEtc, const char *file_name);

/**
 * \fn  UnloadEtcFile (GHANDLE hEtc)
 * \brief Unloads an etc file.
 *
 * This function unloads the etc object generated by using \sa LoadEtcFile 
 * function.
 *
 * \param hEtc Handle of the etc object.
 *
 * \return Returns 0 on success, -1 on error.
 *
 * \sa LoadEtcFile, GetValueFromEtc
 */
	int UnloadEtcFile (GHANDLE hEtc);

/**
 * \fn  GetValueFromEtc (GHANDLE hEtc, const char* pSection,\ 
                const char* pKey, char* pValue, int iLen)
 * \brief Gets value from a configuration etc object.
 *
 * This function gets value from an etc object, similar to GetValueFromEtcFile.
 * This function gets the value of the key \a pKey in the section \a pSection 
 * of the etc object \a hEtc, and saves the value to the buffer pointed to 
 * by \a pValue. 
 *
 * \param hEtc Handle to the etc object.
 * \param pSection The section name in which the value located.
 * \param pKey The key name of the value.
 * \param pValue The value will be saved in this buffer.
 * \param iLen The length in bytes of the buffer. This function will set value
 *        if the iLen is less than 1.
 *
 * \return ETC_OK on success, < 0 on error.
 *
 * \retval ETC_OK               Gets value successfullly.
 * \retval ETC_INVALIDOBJ       Invalid etc object.
 * \retval ETC_SECTIONNOTFOUND  Can not find the specified section in the 
 *                              configuration file.
 * \retval ETC_KEYNOTFOUND      Can not find the specified key in the section.
 * \retval ETC_READONLYOBJ      The etc object is read-only.
 *
 * \sa GetValueFromEtcFile, LoadEtcFile, UnloadEtcFile
 */
	int GetValueFromEtc (GHANDLE hEtc, const char *pSection, const char *pKey, char *pValue, int iLen);

/**
 * \fn int  GetIntValueFromEtc (GHANDLE hEtc, const char* pSection,\
                const char* pKey, int* pValue)
 * \brief Gets the integer value from a configuration etc object.
 *
 * \sa GetValueFromEtc, GetIntValueFromEtcFile
 */
	int GetIntValueFromEtc (GHANDLE hEtc, const char *pSection, const char *pKey, int *pValue);

/**
 * \def SetValueToEtc(GHANDLE hEtc, const char* pSection,\
                const char* pKey, char* pValue)
 * \brief Sets the value in the etc object.
 *
 * This fuctions sets the value in the etc object, somewhat similiar 
 * to \sa SetValueToEtcFile.
 *
 * \sa SetValueToEtcFile, GetValueFromEtc
 */
#define SetValueToEtc(hEtc, pSection, pKey, pValue) \
        GetValueFromEtc(hEtc, pSection, pKey, pValue, -1)


	/** @} end of etc_fns */


#ifdef __cplusplus
}
#endif							/* __cplusplus */

#endif							/* _INC_ETC_H_ */
